/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.googlecode.mindlistening.module.liferecorder;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ObjectNode;
import org.ektorp.AttachmentInputStream;
import org.ektorp.CouchDbConnector;
import org.ektorp.DocumentOperationResult;
import org.ektorp.Revision;
import org.joda.time.Instant;
import org.joda.time.Interval;

/**
 *
 * @author ryan
 */
public class Uploader {

    CouchDbConnector wikiConnector;
    

    public Uploader (CouchDbConnector wikiConnector){

        this.wikiConnector = wikiConnector;
    }

    public void uploadFilesToCouch(File dir, Recorder recorder) {
        List<RecordingWithInterval> recordings = recorder.findRecordings(dir);
        List<Instant> marks = recorder.findMarks(recordings);
        uploadFinalRecordings(recordings);
        List<Interval> markIntervals = recorder.findMarkInterval(marks);
        uploadMarks(markIntervals);
    }

    protected void uploadMarks(List<Interval>  marks) {
        List<JsonNode> bulkJsonFormat = translateMarks(marks);
        wikiConnector.executeBulk(bulkJsonFormat);
    }
    protected List<JsonNode> translateMarks(List<Interval>  marks) {
        List<JsonNode> results = new ArrayList<JsonNode>();
        for (Interval mark : marks) {
            JsonNode translation = translate(mark);
            results.add(translation);
        }
        return results;
    }
    protected JsonNode translate(Interval mark) {
        ObjectMapper mapper = new ObjectMapper();
        ObjectNode root = mapper.createObjectNode();
        root.put("liferecorder", true);

        ObjectNode markObj = mapper.createObjectNode();
        markObj.put("start", mark.getStartMillis());
        markObj.put("length", mark.toDurationMillis() / 1000);
        root.put("mark", markObj);
        return root;
    }

    protected void uploadFinalRecordings(List<RecordingWithInterval> finalRecordings) {
        List<JsonNode> bulkJsonFormat = translate(finalRecordings);
        List<DocumentOperationResult> uploadResults = wikiConnector.executeBulk(bulkJsonFormat);
        for(int i=0; i < finalRecordings.size(); i++) {
            RecordingWithInterval recording = finalRecordings.get(i);
            //DocumentOperationResult result = uploadResults.get(i);

            // these should match based on order!
            FileInputStream fis;
            try {
                List<Revision> revisions = wikiConnector.getRevisions(recording.getId());
                String revision = revisions.get(0).getRev();
                fis = new FileInputStream(recording.getFile());
                AttachmentInputStream ais = new AttachmentInputStream(recording.getFile().getName(),fis, "audio/mp3");
                wikiConnector.createAttachment(recording.getId(), revision, ais);
                ais.close();
                fis.close();
            } catch (Exception ex) {
                Logger.getLogger(LifeRecorderManager.class.getName()).log(Level.SEVERE, null, ex);
            }



        }
    }

    protected List<JsonNode> translate(List<RecordingWithInterval> finalRecordings) {
        List<JsonNode> results = new ArrayList<JsonNode>();
        for (RecordingWithInterval recording : finalRecordings) {
            JsonNode translation = translate(recording);
            results.add(translation);
        }
        return results;
    }

    protected JsonNode translate(RecordingWithInterval recordingInterval) {
        ObjectMapper mapper = new ObjectMapper();
        ObjectNode root = mapper.createObjectNode();
        root.put("_id", recordingInterval.getId());
        root.put("liferecorder", true);

        ObjectNode recording = mapper.createObjectNode();
        recording.put("start", recordingInterval.getInterval().getStartMillis());
        recording.put("length", recordingInterval.getInterval().toDurationMillis() / 1000);
        root.put("recording", recording);
        return root;
    }
}
